﻿using CPAIS.Model;
using CPAIS.Updater;
using System;
using System.Xml;

namespace CPAIS.LogParser.PluginsWithXmlDocument
{
    /// <summary>
    /// Log parser for parsing event log file with XML Root TAG 'WorkflowLog', like:
    /// 
    /// <?xml version="1.0" encoding="UTF-8"?>
    /// <WorkflowLog description="A simple example about the bronchial lung cancer">
    ///     <ProcessInstance id="406287" description="肺癌">
    ///         <Data>
    ///             <Attribute name="Gender">男</Attribute>
    ///             <Attribute name="Birthday">1951-01-01 00:00:00.0</Attribute>
    ///             <Attribute name="Care_Level">2</Attribute>
    ///         </Data>
    ///         <AuditTrailEntry>
    ///             <WorkflowModelElement>Admission</WorkflowModelElement>
    ///             <EventType>complete</EventType>
    ///             <Timestamp>2008-09-01T14:03:00.000+08:00</Timestamp>
    ///         </AuditTrailEntry>
    ///     </ProcessInstance>
    /// </WorkflowLog>
    /// 
    /// OR
    /// 
    /// <?xml version="1.0" encoding="UTF-8"?>
    /// <WorkflowLog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://is.tm.tue.nl/research/processmining/WorkflowLog.xsd" description="Patient trace repository">
    ///     <ProcessInstance id="410770" description="Breast cancer">
    ///         <Data>
    ///             <Attribute name="Care Level">2</Attribute>
    ///             <Attribute name="Department">七病区</Attribute>
    ///             <Attribute name="Patient_Birthday">Oct 22 1958 12:00AM</Attribute>
    ///             <Attribute name="Patient_Gender">女</Attribute>
    ///         </Data>
    ///         <AuditTrailEntry>
    ///             <WorkflowModelElement>Admission</WorkflowModelElement>
    ///             <EventType>complete</EventType>
    ///             <Timestamp>2008-10-20T17:29:00.000+08:00</Timestamp>
    ///         </AuditTrailEntry>
    ///     </ProcessInstance>
    /// </WorkflowLog>
    /// 
    /// </summary>
    public class LogParserC : ILogParserWithXmlDocument
    {
        #region String used for parsing XML file
        private const string EventLog = "WorkflowLog";
        private const string Description = "description";
        private const string ProcessInstance = "ProcessInstance";
        private const string ID = "id";
        private const string Data = "Data";
        private const string Attribute = "Attribute";
        private const string Name = "name";
        private const string Gender = "Gender";
        private const string Patient_Gender = "Patient_Gender";
        private const string Birthday = "Birthday";
        private const string Patient_Birthday = "Patient_Birthday";
        private const string Department = "Department";
        private const string AuditTrailEntry = "AuditTrailEntry";
        private const string WorkflowModelElement = "WorkflowModelElement";
        private const string EventType = "EventType";
        private const string Timestamp = "Timestamp";
        private const string Complete = "complete";
        private const string Admission = "Admission";
        private const string Discharge = "Discharge";

        private const string Male = "男";
        private const string Female = "女";
        #endregion
        
        public string XmlTag
        {
            get { return EventLog; }
        }

        public void Parse(LogModel logModel, XmlNode rootNode, StateUpdater updater)
        {
            foreach (XmlNode node in rootNode.ChildNodes)
            {
                if (node.Name != ProcessInstance)
                    continue;

                string strPID = node.Attributes[ID].Value.Trim();
                string strDescription = node.Attributes[Description].Value.Trim();

                Trace trace = new Trace(logModel, strPID);
                trace.AddDiagnosis(strDescription);

                foreach (XmlNode sNode in node.ChildNodes)
                {
                    if (sNode.Name == Data)
                    {
                        foreach (XmlNode tNode in sNode.ChildNodes)
                        {
                            if (tNode.Name == Attribute)
                            {
                                string strType = tNode.Attributes[Name].Value.Trim();
                                string strValue = tNode.InnerText.Trim();
                                if (strType == Gender || strType == Patient_Gender)
                                    trace.Sex = strValue == Male ? SexType.Male : (strValue == Female ? SexType.Female : SexType.Unknown);
                                else if (strType == Birthday || strType == Patient_Birthday)
                                {
                                    DateTime birthday = DateTime.Parse(strValue);
                                    trace.Birthday = birthday;
                                }
                                else if (strType == Department)
                                    trace.Department = strValue;
                            }
                        }
                    }
                    else if (sNode.Name == AuditTrailEntry)
                    {
                        string strType = "";
                        string strState = "";
                        string strTimestamp = "";
                        foreach (XmlNode tNode in sNode.ChildNodes)
                        {
                            if (tNode.Name == WorkflowModelElement)
                                strType = tNode.InnerText.Trim();
                            else if (tNode.Name == EventType)
                                strState = tNode.InnerText.Trim();
                            else if (tNode.Name == Timestamp)
                                strTimestamp = tNode.InnerText.Trim();
                        }
                        if (strState == Complete)
                        {
                            DateTime timestamp = DateTime.Parse(strTimestamp);
                            if (strType == Admission)
                                trace.Admit = timestamp;
                            else if (strType == Discharge)
                                trace.Discharge = timestamp;

                            ActionEvent entry = new ActionEvent(trace, timestamp, strType);
                            trace.AddAction(entry);
                        }
                    }
                }
                trace.OrderTrace();
                logModel.AddTrace(trace);
                if (updater != null)
                    updater.UpdateMessage(string.Format("{0} traces have been loaded...", logModel.TraceCount));
            }
        }
    }
}
